package com.smile.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.smile.api.LoginLogApi;
import com.smile.api.MenuApi;
import com.smile.api.RoleApi;
import com.smile.api.UserApi;
import com.smile.commons.action.ActionUtils;
import com.smile.commons.constant.StateConstant;
import com.smile.commons.md5.MD5Util;
import com.smile.commons.page.R;
import com.smile.config.RedisConstant;
import com.smile.config.UserUtilsByLogin;
import com.smile.model.request.GetRoleByIdRequest;
import com.smile.model.request.GetUserInfoByUserNameRequest;
import com.smile.model.response.GetMenusByRoleIdResponse;
import com.smile.model.response.GetRoleByIdResponse;
import com.smile.model.response.GetUserInfoByUserNameResponse;
import com.smile.model.response.ShowMenuListResponse;
import com.smile.request.AddLoginLogRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/")
@Slf4j
public class SSOServerController {

    @Autowired
    private UserApi userApi;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MenuApi menuApi;

    @Autowired
    private RoleApi roleApi;

    @Autowired
    private LoginLogApi loginLogApi;


    @PostMapping("/sso/*")
    public Object ssoRequest() {
        return SaSsoServerProcessor.instance.dister();
    }


    @Autowired
    private void configSso(SaSsoServerTemplate ssoServerTemplate) {


        // 配置：登录处理函数
        ssoServerTemplate.strategy.doLoginHandle = (name, pwd) -> {
            try {

                long startTime = System.nanoTime();


                GetUserInfoByUserNameRequest getUserInfoByUserNameRequest = new GetUserInfoByUserNameRequest();
                getUserInfoByUserNameRequest.setUserName(UserUtilsByLogin.getName());
                R<GetUserInfoByUserNameResponse> userInfoByUserName = userApi.getUserInfoByUserName(getUserInfoByUserNameRequest);
                if (ObjectUtil.isNull(userInfoByUserName) || ObjectUtil.isNull(userInfoByUserName.getData())) {
                    return new SaResult(15000, "该用户不存在", "");
                }
                if(userInfoByUserName.getData().getStatus()==2){
                    return new SaResult(15000, "当前账号已被禁用，请联系管理员", "");
                }
                System.out.println(UserUtilsByLogin.getLoginType());

                GetUserInfoByUserNameResponse getUserInfoByUserNameResponse = userInfoByUserName.getData();
                String password = MD5Util.md5WithSalt(UserUtilsByLogin.getPwd(), getUserInfoByUserNameResponse.getSalt());
                if (password.equals(getUserInfoByUserNameResponse.getPassword())) {
                    Long roleId = getUserInfoByUserNameResponse.getRoleId();
                    GetRoleByIdRequest getRoleByIdRequest = new GetRoleByIdRequest();
                    getRoleByIdRequest.setId(roleId);
                    R<GetRoleByIdResponse> roleById1 = roleApi.getRoleById(getRoleByIdRequest);
                    if (ObjectUtil.isNotNull(roleById1) && ObjectUtil.isNotNull(roleById1.getData())) {

                        // 角色权限校验
                        if (StateConstant.DISABLE_STATE.equals(roleById1.getData().getStatus())) {
                            return new SaResult(15002, "当前账号没有权限，请联系管理员!", "");
                        }
                        // 取消使用role_value作为权限标识
                        /*if (StrUtil.isNotBlank(roleById1.getData().getRoleValue())) {
                            if (!roleById1.getData().getRoleValue().equals(UserUtilsByLogin.getLoginType()) ||
                                    StateConstant.CLOSING_STATE.equals(roleById1.getData().getStatus())) {
                                return new SaResult(15002, "用户无权限登录!", "");
                            }
                        }*/

                        redisTemplate.opsForValue().set(RedisConstant.ROLE_PREFIX + getUserInfoByUserNameResponse.getId(), roleById1.getData().getRoleValue());
                    }

                    if (ObjectUtil.isNull(roleById1) || ObjectUtil.isNull(roleById1.getData())) {
                        return List.of();
                    }

                    R<List<GetMenusByRoleIdResponse>> menusByRoleId = menuApi.getMenusByRoleId(roleId);

                    List<String> permissionList = new ArrayList<>();

                    if (ObjectUtil.isNotNull(menusByRoleId) || ObjectUtil.isNotNull(menusByRoleId.getData())) {
                        R<List<ShowMenuListResponse>> list = menuApi.listAll();
                        if (ObjectUtil.isNotNull(list) || CollectionUtil.isNotEmpty(list.getData())) {

                            menusByRoleId.getData().forEach(item -> {
                                Long menuId = item.getMenuId();
                                if (ObjectUtil.isNotNull(list) || CollectionUtil.isNotEmpty(list.getData())) {
                                    list.getData().forEach(item1 -> {
                                        if (menuId.equals(item1.getId())) {
                                            permissionList.add(item1.getMenuName());
                                        }
                                    });
                                }
                            });
                        }

                    }

                    redisTemplate.opsForValue().set(RedisConstant.PERMISSION_PREFIX + getUserInfoByUserNameResponse.getId(), permissionList);

                    // 登录
                    StpUtil.login(getUserInfoByUserNameResponse.getId(), new SaLoginModel().setTimeout(-1));

                    long endTime = System.nanoTime();


                    long times = endTime - startTime;

                    AddLoginLogRequest addLoginLogRequest = new AddLoginLogRequest();
                    addLoginLogRequest.setDescription("登录成功");
                    addLoginLogRequest.setUserName(UserUtilsByLogin.getName());
                    addLoginLogRequest.setTimes(times);
                    addLoginLogRequest.setLoginTime(LocalDateTime.now());
                    addLoginLogRequest.setExplorer(ActionUtils.getExplorerInfo());
                    addLoginLogRequest.setOperateSystem(ActionUtils.getSystemInfo());
                    addLoginLogRequest.setIpAddress(ActionUtils.getIpInfo());
                    loginLogApi.addLoginLog(addLoginLogRequest);

                    //TODO 这里为了方便用Apipost调试暂时注掉

                    String userAgent = SaHolder.getRequest().getHeader("User-Agent");
                    log.info("userAgent:" + userAgent);
                    log.info("登录时间为:" + times);


                    return SaResult.ok("登录成功！").setData(StpUtil.getTokenValue());
                } else {
                    long endTime = System.nanoTime();


                    long times = endTime - startTime;
                    AddLoginLogRequest addLoginLogRequest = new AddLoginLogRequest();
                    addLoginLogRequest.setDescription("登录失败");
                    addLoginLogRequest.setUserName(UserUtilsByLogin.getName());
                    addLoginLogRequest.setTimes(times);
                    addLoginLogRequest.setLoginTime(LocalDateTime.now());
                    addLoginLogRequest.setExplorer(ActionUtils.getExplorerInfo());
                    addLoginLogRequest.setOperateSystem(ActionUtils.getSystemInfo());
                    addLoginLogRequest.setIpAddress(ActionUtils.getIpInfo());
                    loginLogApi.addLoginLog(addLoginLogRequest);
                    return new SaResult(15001, "账号或密码有误!", "");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }


            // 此处仅做模拟登录，真实环境应该查询数据库进行登录
        };
    }


    @PostMapping("/sso/signout")
    @SaIgnore
    public SaResult signout() {
        if (StpUtil.isLogin()) {
            StpUtil.logout();
        }
        return new SaResult(200, "token已失效，请重新登录", "");
    }

}
